package com.hsgene.order.service.impl;

import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.character.CharactersConstant;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.generator.constants.GeneratorEnum;
import com.hsgene.generator.dto.GeneratorDto;
import com.hsgene.message.domain.PushInfo;
import com.hsgene.order.domain.disease.GeneticDisease;
import com.hsgene.order.domain.reserve.DifuPeopleInfo;
import com.hsgene.order.domain.reserve.DoctorOrderInfo;
import com.hsgene.order.domain.reserve.ReserveOrderInfoDto;
import com.hsgene.order.domain.reserve.ReserveOrderResultDto;
import com.hsgene.order.domain.reserve.product.GeneticTestingProductDto;
import com.hsgene.order.domain.reserve.product.ProductCancers;
import com.hsgene.order.dto.OrderSumPriceCommission;
import com.hsgene.order.persistence.ReserveOrderRepository;
import com.hsgene.order.service.ReserveOrderService;
import com.hsgene.order.service.api.GeneratorService;
import com.hsgene.order.service.api.MessageService;
import com.hsgene.order.service.api.NotificationService;
import com.hsgene.order.service.api.ProductService;
import com.hsgene.product.domain.GeneticTestingPackage;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 预约订单接口实现
 *
 * @author wxf
 * @date 2018/9/17 14:07
 **/
@Service
public class ReserveOrderServiceImpl implements ReserveOrderService {

    @Resource
    private ReserveOrderRepository reserveOrderRepository;

    @Resource
    private GeneratorService generatorService;

    @Resource
    private MessageService messageService;

    @Resource
    private ProductService productService;

    @Value("${notice.difu.info}")
    private String messageContent;

    @Resource
    private NotificationService notificationService;

    /**
     * 预约下单
     *
     * @param orderInfoDto 订单信息
     * @param date         时间
     * @param doctorMap    医生信息
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public ReserveOrderResultDto doctorAddOrder(ReserveOrderInfoDto orderInfoDto, Date date, Map<String, Object>
            doctorMap) throws IllegalAccessException {
        //订单编号
        String orderNo = getOrderNo(GeneratorEnum.MEDI.getType());
        //订单id
        String orderId = UUID32.randomUUIDString();
        List<String> packageIds = new ArrayList<>();
        orderInfoDto.getProducts().stream().forEach(product -> {
            packageIds.add(product.getProductId());
        });
        //订单总金额
        OrderSumPriceCommission sum = reserveOrderRepository.getProductSumPrice(packageIds);
        //TODO 预留折扣活动接口
        if (sum == null) {
            return new ReserveOrderResultDto();
        }
        //预约采样时间格式转换
        long testTime = orderInfoDto.getTestingTime().longValue();
        Date testDate = new Date(testTime);
        String userId = orderInfoDto.getUserId();
        //将记录先插入订单表genetic_testing_order
        String name = (String) doctorMap.get("name");
        String phone = (String) doctorMap.get("phone");
        String difuId = (String) doctorMap.get("userId");
        reserveOrderRepository.addOrder(orderId, orderNo, userId, sum, testDate, orderInfoDto, date, name, phone);
        //将套餐信息存入套餐表genetic_testing_order_package
        if (!packageIds.isEmpty()) {
            for (String packageId : packageIds) {
                ApiResult<GeneticTestingPackage> packageApiResult = productService.getPackageById(packageId, 1);
                if (packageApiResult == null || !packageApiResult.isSucc()) {
                    throw new IllegalAccessException("获取套餐数据出现异常");
                }
                reserveOrderRepository.addPackageToOrder(UUID32.randomUUIDString(), packageId, testDate, orderId,
                        packageApiResult.getData().getGeneticTestingProduct());
            }
        }

        //获取疾病id
        Stream<ProductCancers> cancersStream = orderInfoDto.getCancers().stream();
        String cancerIds = StringUtils.join(cancersStream.map(ProductCancers::getName).collect(Collectors.toList()),
                CharactersConstant.COMMA_EN);
        //根据疾病id获取疾病名称
        List<String> diseaseNames = new LinkedList<>();
        orderInfoDto.getCancers().stream().forEach(cancers -> {
            String diseaseName = reserveOrderRepository.getDiseaseNameById(cancers);
            diseaseNames.add(diseaseName);
        });
        //插入genetic_testing_order_addtion_a信息
        reserveOrderRepository.addOrderAddtionA(UUID32.randomUUIDString(), orderId, difuId, testDate, date,
                cancerIds, StringUtils.join(diseaseNames, CharactersConstant.COMMA_EN));
        //插入genetic_testing_order_addtion_b信息
        reserveOrderRepository.addOrderAddtionB(UUID32.randomUUIDString(), orderId, sum);
        //插入医生预约订单表
        String productIds = StringUtils.join(orderInfoDto.getProducts().stream().map
                (GeneticTestingProductDto::getProductId).collect
                (Collectors.toList()), CharactersConstant.COMMA_EN);
        reserveOrderRepository.addDoctorOrder(UUID32.randomUUIDString(), orderId, cancerIds, productIds, date,
                orderInfoDto.getRemark());
        //TODO 用户信息存入数据库表(医生可能没在数据库中)
        reserveOrderRepository.inserUserInfo(userId, orderInfoDto.getUserName(), orderInfoDto.getUserType());
        //套餐被用标记
        for (String packageId : packageIds) {
            GeneticTestingPackage testingPackage = new GeneticTestingPackage();
            testingPackage.setId(packageId);
            testingPackage.setIsUsed(1);
            productService.updateProduct(testingPackage);
        }
        ReserveOrderResultDto resultDto = new ReserveOrderResultDto(orderNo, sum.getTotalCharges(), date.getTime());
        //发送系统消息
        //TODO 短信通知地服务人员
        if (StringUtils.isNotEmpty(difuId)) {
            //获取地服电话、name
            DifuPeopleInfo difuInfo = reserveOrderRepository.getDifuPeopleInfo(difuId);
            messageService.sendMessage(String.format(messageContent, difuInfo.getName()),
                    difuInfo.getPhone());
            PushInfo pushInfo = new PushInfo("基因检测",
                    String.format(messageContent, difuInfo.getName()), orderId, "0", "1");
            notificationService.pushNotification(pushInfo, difuId, false);
        }
        return resultDto;
    }

    /**
     * 获取疾病列表
     *
     * @return
     */
    @Override
    public List<GeneticDisease> getGeneticDisease() {
        //先获取根结点
        GeneticDisease root = reserveOrderRepository.getRootDisease();
        //递归获取子结点
        return getDiseaseInfo(root.getId());
    }

    private List<GeneticDisease> getDiseaseInfo(String id) {
        List<GeneticDisease> childrenList = reserveOrderRepository.getDiseaseChildren(id);
        List<GeneticDisease> allChildren = new LinkedList<>();
        for (GeneticDisease child : childrenList) {
            List<GeneticDisease> grandson = getDiseaseInfo(child.getId());
            child.setDiseaseChildren(grandson);
            allChildren.add(child);
        }
        return allChildren;
    }

    private String checkStringBuild(StringBuilder builder) {
        if (builder == null || builder.length() < 1) {
            return null;
        }
        return builder.toString().substring(0, builder.length() - 1);
    }

    private String getOrderNo(String type) {
        ApiResult<GeneratorDto> generatorResult = generatorService.numberGenerator(type, 0, 0);
        if (generatorResult.isSucc()) {
            return generatorResult.getData().getSerialNumber();
        }
        return UUID32.randomUUIDString();
    }
}
